package org.sklse.learningassistant.service.resource;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import org.apache.http.HttpHost;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.sklse.learningassistant.bean.resource.Question;
import org.sklse.learningassistant.repository.resource.QuestionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author masker
 * @date 2018/4/17 下午9:08
 */
@Service
public class QuestionService {

    @Autowired
    private QuestionRepository questionRepository;

    private RestHighLevelClient client;

    @Value("${spring.elasticsearch.hostname}")
    private String esHostname;

    @PostConstruct
    public void before() {
        client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost(esHostname, 9200, "http"),
                        new HttpHost(esHostname, 9201, "http")));
    }

    @PreDestroy
    public void after() throws IOException {
        client.close();
    }
    public void add() throws IOException {
        List<Question> questions=questionRepository.findAll();
        for(Question question:questions){
            IndexRequest request = new IndexRequest(Question.ES_INDEX, Question.ES_TYPE, String.valueOf(question.getId()));
            request.source(JSON.toJSONString(question), XContentType.JSON);
            IndexResponse response = client.index(request);
        }
    }

    public List<Question> search(String text,int pageNumber,int pageSize) throws IOException {
        if (text != null && !text.equals("") && !text.equals(" ")) {
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("title", text);
            matchQueryBuilder.fuzziness(Fuzziness.AUTO);
            matchQueryBuilder.prefixLength(3);
            matchQueryBuilder.maxExpansions(10);
            searchSourceBuilder.query(matchQueryBuilder);
            searchSourceBuilder.from(pageNumber * pageSize);
            searchSourceBuilder.size(pageSize);

            SearchRequest searchRequest = new SearchRequest(Question.ES_INDEX);
            searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
            searchRequest.source(searchSourceBuilder);

            SearchResponse searchResponse = client.search(searchRequest);
            SearchHits searchHits = searchResponse.getHits();
            List<Question> questionList = new ArrayList<>();
            Gson gson = new Gson();
            for (SearchHit hit : searchHits) {
                questionList.add(gson.fromJson(hit.getSourceAsString(), Question.class));
            }

            Long totalElements = searchHits.totalHits;
            int totalPages = (int) Math.ceil(totalElements / pageSize);
            boolean hasNextPage = pageNumber < totalPages;
            boolean hasPreviousPage = pageNumber > totalPages;

            //TODO abstract the pagination
            return questionList;
//            Page<Question> questionPage = new Page<>();
//            questionPage.setContent(questionList);
//            questionPage.setHasNextPage(hasNextPage);
//            questionPage.setHasPreviousPage(hasPreviousPage);
//            questionPage.setTotalElements(totalElements);
//            questionPage.setTotalPages(totalPages);
//            questionPage.setPageNumber(pageNumber);
//            questionPage.setPageSize(pageSize);
//            return questionPage;
        }else{
            return null;
        }
    }

    public Question findById(int id){
        return questionRepository.findById(id);
    }
}